Skip to content

feat(gui): add a Settings → Assets tab (refresh, clear cache, auto-download, open folder)#142

Merged
AprilNEA merged 4 commits into
masterfrom
feat/assets-settings
Jun 13, 2026
Merged

feat(gui): add a Settings → Assets tab (refresh, clear cache, auto-download, open folder)#142
AprilNEA merged 4 commits into
masterfrom
feat/assets-settings

Conversation

@AprilNEA

@AprilNEA AprilNEA commented Jun 5, 2026

Copy link
Copy Markdown
Owner

What

Adds a Settings → Assets tab to manage device-image assets, with four controls:

Control Behavior
Automatically download device images (toggle) Gates the automatic startup sync on a new persisted auto_download_assets setting (default on). Off = the app makes no asset network requests at all; bundled art and the synthetic silhouette still render.
Refresh assets (button) Force-fetches images for the connected devices now, bypassing the should_run policy — so a release build that ships bundled art (and otherwise never syncs at runtime) can still pull updated renders between releases.
Clear cache (button) Shows the on-disk cache size and wipes the per-user cache, then re-fetches. The read-only app bundle is a separate tier and keeps serving.
Cache location (button) Reveals the downloaded-images folder in Finder.

How it's wired

The asset sync lives on the main event loop (the AtomicU8 state machine from #140). Manual actions reach it through a new AssetControl global channel — the same pattern as PairingControl for the Add-Device window. The loop now:

  • keeps the latest inventory, so a manual Refresh syncs the current devices immediately and resets the retry backoff;
  • gates the automatic sync on the auto_download_assets setting (read from AppState per snapshot);
  • handles a new asset_ctrl_rx arm: ClearCache wipes the cache then both commands force a fresh fetch (sync_assets(.., force = true) skips should_run).

New asset-module helpers back the buttons: cache_size_bytes, clear_cache, reveal_cache_in_file_manager.

Design notes

  • The toggle does double duty. It's a privacy/offline control (off = zero asset network traffic) and — combined with the Refresh button — the answer to a real gap: a release build with bundled assets never syncs at runtime (should_run returns false), so fixes that only update the live index.json (e.g. fix(assets): match devices against every model id a depot lists #137's modelIds) wouldn't reach those users without a Refresh. Refresh forces the fetch; the toggle, when on, doesn't change the existing release-bundle behavior (auto-sync stays gated by should_run).
  • No "Fetch all". The full asset set is ~600 MB of devices a user mostly doesn't own and would never see; the runtime model stays "fetch what's connected." Refresh covers the only sensible case.
  • Back-compat: auto_download_assets is #[serde(default = "default_true")], so existing config files keep the current (auto-download) behavior; schema_version is unchanged.

i18n

New strings are translated for ja / ru / zh-CN / zh-HK / zh-TW (English msgid doubles as the key, so missing locales fall back to English). ja and ru are best-effort — corrections welcome.

Test plan

Follow-up to #137 / #140.

@AprilNEA AprilNEA added type: feature New feature request area: gui Graphical user interface area: assets Icons, images, and bundled assets area: config Configuration files, persistence, and settings labels Jun 5, 2026
@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a Settings → Assets tab with four controls: a toggle to gate automatic device-image downloads, a Refresh button (force-fetches for connected devices, bypassing the sync_enabled release-build gate), a Clear cache button (wipes the per-user cache then re-fetches), and a Cache location button (opens the folder in Finder). The main event loop gains a latest_inv snapshot, a deferred_manual slot to safely queue commands mid-sync, and an AssetControl global channel matching the existing PairingControl pattern.

  • main.rs: AssetControl channel wired; deferred_manual correctly prevents cache wipes from racing in-flight syncs; latest_inv updated only on InventoryHealth::Ready to avoid shrinking on pre-enumeration stale snapshots.
  • config.rs / state.rs: New auto_download_assets field defaults to true via #[serde(default = \"default_true\")] for back-compat; persisted atomically with an early-return no-op guard.
  • asset/mod.rs: New cache_size_bytes, clear_cache, and reveal_cache_in_file_manager helpers; reveal_cache_in_file_manager is macOS-only at runtime but the "Cache location" UI row is rendered on all platforms.
  • Locales: All 18 supported locales receive the new strings.

Confidence Score: 5/5

Safe to merge; the core sync deferral and cache-wipe logic is well-reasoned and the previously flagged race conditions are addressed.

The deferred_manual queue correctly prevents cache wipes from racing in-flight syncs, the auto_download gate is read fresh on each inventory snapshot, and the back-compat serde default is in place. Two non-blocking quality issues remain: the Cache location button creates the cache dir but never opens a file manager on Linux, and a clear_cache() filesystem failure still resets in-memory bookkeeping — both cause wasteful behavior in edge cases but not data loss or incorrect state for typical users.

crates/openlogi-gui/src/asset/mod.rs (reveal_cache_in_file_manager non-macOS path) and crates/openlogi-gui/src/main.rs (clear_cache error handling before state reset)

Important Files Changed

Filename Overview
crates/openlogi-core/src/config.rs Adds auto_download_assets: bool field to AppSettings with #[serde(default = "default_true")] for back-compat and a matching Default impl entry; clean and consistent with existing fields.
crates/openlogi-gui/src/asset/mod.rs Adds cache_size_bytes, clear_cache, and reveal_cache_in_file_manager helpers; the "Cache location" button is visible on Linux but open_in_file_manager is a no-op there (no xdg-open fallback).
crates/openlogi-gui/src/main.rs Wires AssetControl global channel, latest_inv tracking, deferred_manual deferral, and auto-download toggle; clear_cache() failure doesn't prevent the in-memory state reset that follows it.
crates/openlogi-gui/src/windows/settings.rs Adds the Assets settings page with four controls; asset_cache_desc computed once at window open (not per render); toggle re-enable correctly dispatches an immediate Refresh.
crates/openlogi-gui/src/state.rs Adds set_auto_download_assets with an early-return on no-op and atomic config persistence; straightforward and consistent with existing setter patterns.

Sequence Diagram

sequenceDiagram
    participant UI as Settings Assets UI
    participant Ctrl as AssetControl channel
    participant Main as Main Event Loop
    participant FS as Filesystem
    participant Net as assets.openlogi.org

    UI->>Ctrl: send Refresh
    Ctrl->>Main: asset_ctrl_rx.recv()
    alt sync_running is true
        Main->>Main: "deferred_manual = Some(Refresh)"
        Note over Main: waits for sync outcome
        Main->>Ctrl: re-send deferred via asset_ctrl_self_tx
    else sync_running is false
        Main->>Main: "sync_running = true"
        Main->>Net: spawn thread, run_asset_sync(latest_inv)
        Net-->>Main: SyncOutcome ok, keys
        Main->>Main: "sync_running = false, synced_keys union keys"
    end

    UI->>Ctrl: send ClearCache
    Ctrl->>Main: asset_ctrl_rx.recv()
    alt sync_running is true
        Main->>Main: "deferred_manual = Some(ClearCache), beats Refresh"
    else sync_running is false
        Main->>FS: clear_cache, remove_dir_all
        Main->>Main: "synced_keys.clear, index_refreshed=false, cache=new"
        Main->>UI: cx.refresh_windows
        Main->>Net: spawn thread, run_asset_sync(latest_inv)
    end

    UI->>UI: toggle auto_download ON
    UI->>Ctrl: send Refresh immediately
Loading

Reviews (6): Last reviewed commit: "fix(gui): defer manual asset sync while ..." | Re-trigger Greptile

Comment thread crates/openlogi-gui/src/main.rs Outdated
Comment thread crates/openlogi-gui/src/windows/settings.rs
Comment thread crates/openlogi-gui/src/main.rs Outdated
A persisted on/off preference (default on, backward-compatible via serde
default) for whether the GUI fetches device images from the network when
a device connects. Consumed by the runtime sync and the upcoming
Settings → Assets tab; off keeps the app fully offline.
@AprilNEA AprilNEA force-pushed the feat/assets-settings branch from 79e2938 to 2f24bd9 Compare June 13, 2026 08:35
AprilNEA added 3 commits June 13, 2026 16:46
A new Assets page in Settings with four controls:

- Automatically download device images — a toggle gating the startup
  sync on the new auto_download_assets setting; off makes the app issue
  no asset network requests (bundled art + silhouette still render).
- Refresh assets — force-fetches images for the connected devices now,
  bypassing the should_run policy (so a release build with bundled art
  can still pull updated renders between releases).
- Clear cache — shows the on-disk cache size and wipes the per-user
  cache, then re-fetches.
- Cache location — reveals the downloaded-images folder in Finder.

Manual actions reach the sync (which lives on the main event loop) via a
new AssetControl global channel, mirroring PairingControl. The loop keeps
the latest inventory so a manual refresh syncs the current devices
immediately and resets the retry backoff. Asset cache helpers
(cache_size_bytes / clear_cache / reveal_cache_in_file_manager) and a
`force` flag on the sync entrypoint back the buttons. Strings translated
for ja/ru/zh-CN/zh-HK/zh-TW (ja/ru best-effort, English-key fallback).
- Compute the asset-cache size once when the Settings window opens and
  store it on the view, instead of re-walking the cache dir on the main
  thread every render. (Greptile)
- Extract the macOS Finder reveal into a cfg-gated helper so the early
  return isn't the function's last statement on non-macOS — CI clippy
  flagged needless_return on the Linux build (local macOS clippy can't
  see that path).

The original commit also skipped the manual sync on an empty inventory
to keep the old SYNC_DONE latch from wedging the auto-sync gate; the
rebased loop has no such latch (it re-arms per model set, #220) and an
index-only refresh is first-class there (#218), so that guard is
dropped.
A manual Refresh / Clear that arrives while a background sync is running
is stashed in `deferred_manual` instead of acting immediately, and the
sync-outcome arm re-issues it (through the existing control channel) the
moment that sync finishes. So a Clear never wipes the cache out from
under the in-flight fetch's writes, and a second writer is never spawned
alongside it. A queued Clear is not downgraded by a later Refresh.
@AprilNEA AprilNEA force-pushed the feat/assets-settings branch from 2f24bd9 to 1237091 Compare June 13, 2026 08:47
@AprilNEA AprilNEA merged commit 1220e31 into master Jun 13, 2026
8 checks passed
@AprilNEA AprilNEA deleted the feat/assets-settings branch June 13, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: assets Icons, images, and bundled assets area: config Configuration files, persistence, and settings area: gui Graphical user interface type: feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant